﻿using SimDev.Config;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Xml.Serialization;

namespace SimDev.ViewModel
{
    [AttributeUsage(AttributeTargets.Class)]
    public class VersionAttribute : Attribute
    {
        public string Model { get; set; }
        public string Date { get; set; }
        public string Describtion { get; set; }
    }
    public interface IRTU
    {
      
        string Model { get; }

         DTU DTU { get; set; }

         int Address { get; set; }

         List<Register> Registers{get;set;}

        //List<Register> WriteRegisters { get; set; }

        ArraySegment<byte> HandleModbus(byte[] modbuscommand);

        RTUConfig GetConfig();

         void Setup(DTU dtu, int address, List<Register> registers, string model);
       
    }

    public class InverseConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool v = (bool)value;
            return !v;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public static class RegisterExtentions
    {
        static Random _random = new Random();
        public static ushort GetValue(this Register reg)
        {
            if (reg.RegSimConfig.ValueIsRandom)
            {
                return (ushort)_random.Next(reg.RegSimConfig.Minimum, reg.RegSimConfig.Maximum);
            }
            else
            {
                return reg.RegSimConfig.FixValue;
            }

        }

    }


    //[Version( Model  ="2S")]
    public class RTU:IRTU
    {

        byte[] _regBuffer = new byte[1024];
        byte[] _crc = new byte[2];
        public DTU DTU { get; set; }

 

        RTUConfig _Config=new RTUConfig();

        public int Address { get; set; }
        public List<Register> Registers
        {
            get ;
            set ;
        }
       
   
        public string Model { get; private set; }



        ArraySegment<byte> HandleModbus3(byte[] modbuscommand)
        {
            ushort regStartAddr;
            ushort regCount;

            regStartAddr = (byte)((modbuscommand[2] << 8) + modbuscommand[3]);//起始地址 
            regCount = (byte)((modbuscommand[4] << 8) + modbuscommand[5]);//读取寄存器个数

            var regs = Registers.Where(r => (r.ReadAddress >= regStartAddr && r.ReadAddress <= (regStartAddr + regCount))).ToList();
            _regBuffer.Initialize();
            _regBuffer[0] = modbuscommand[0];
            _regBuffer[1] = modbuscommand[1];
            _regBuffer[2] = (byte)(regCount * 2);

            for (int i = 0; i < regCount; ++i)
            {
                var reg = regs[i];
                ushort v = reg.GetValue();
                _regBuffer[3 + 2 * i] = (byte)(v >> 8);
                _regBuffer[4 + 2 * i] = (byte)v;

            }

            Helper.GetCRC(_regBuffer, ref _crc, 0, regCount * 2 + 3);
            _regBuffer[regCount * 2 + 3] = _crc[0];
            _regBuffer[regCount * 2 + 4] = _crc[1];

            return new ArraySegment<byte>(_regBuffer, 0, regCount * 2 + 5);
            
        }



        ArraySegment<byte> HandleModbus6(byte[] modbuscommand)
        {
            //解析modbus协议
            int writeAddress = (modbuscommand[2] << 8) + modbuscommand[3];
            int writeValue = (modbuscommand[4] << 8) + modbuscommand[5];
            var reg= Registers.Single(r => r.WriteAddress == writeAddress);
            reg.RegSimConfig.FixValue = (ushort)writeValue;
            reg.RegSimConfig.ValueIsRandom = false;
            return new ArraySegment<byte>(modbuscommand, 0,modbuscommand.Length); 
        }


        public ArraySegment<byte> HandleModbus(byte[] modbuscommand)
        {
            if (modbuscommand[0] != Address) return default(ArraySegment<byte>);
            switch(modbuscommand[1])             
            {
                case 3:
                    return HandleModbus3(modbuscommand);
                case 6:
                    return HandleModbus6(modbuscommand); 
            } 
            return default(ArraySegment<byte>); 
        }


        public void Setup(DTU dtu, int address, List<Register> registers, string model)
        {
            DTU = dtu;
            Address = address;
            Registers =  new List<Register>();
            Model = model;

            if (registers != null)
            {
                registers.ForEach(r =>
                {
                    Registers.Add(new Register()
                    {
                        ReadAddress = r.ReadAddress,
                        WriteAddress=r.WriteAddress,
                        ReadName = r.ReadName,
                        DisplayFormat = r.DisplayFormat,
                        Type = r.Type,
                        RegSimConfig = new RegSimConfig()
                        {
                            FixValue =r.RegSimConfig.FixValue,
                            Maximum =r.RegSimConfig.Maximum,
                            Minimum =r.RegSimConfig.Minimum,
                            ValueIsRandom = r.RegSimConfig.ValueIsRandom
                        }

                    });
                });
            } 
        }

        public RTUConfig GetConfig()
        {
            _Config.Address = this.Address;
            _Config.Registers = this.Registers;
           
            _Config.Model = Model;
            return _Config;
        }
    }
}
